#ifndef MODBUS_PROTOCOL_H
#define MODBUS_PROTOCOL_H

#include <cstdint>
#include <string>
#include <vector>
#include <map>

// Modbus RTU 通讯参数
const int MODBUS_BAUDRATE = 9600;
const int MODBUS_DATABITS = 8;
const int MODBUS_STOPBITS = 1;

// 数据类型枚举
enum class DataType : uint8_t {
    UINT16,
    FLOAT32
};

// 访问类型枚举
enum class AccessType : uint8_t {
    READ_ONLY,
    READ_WRITE
};

// 仪器状态枚举
enum class InstrumentStatus : uint16_t {
    RUNNING = 0,
    MAINTENANCE = 1,
    FAULT = 2,
    CALIBRATION = 3,
    CHECK = 4,
    MEASURING = 6,
    STANDARD = 7,
    STANDBY = 8,
    OPERATION_MAINTENANCE = 9,
    OTHER = 10
};

// 报警类型枚举
enum class AlarmType : uint16_t {
    NO_ALARM = 0,
    SYSTEM_FAULT = 1,
    POWER_FAULT = 2,
    REAGENT_SHORTAGE = 3,
    DISTILLED_WATER_SHORTAGE = 4,
    HEATING_FAULT = 5,
    RESIDUAL_DISCHARGE_FAULT = 6,
    OVER_RANGE_ABNORMAL = 7,
    OTHER_FAULT = 8,
    SAMPLE_REAGENT_TIMEOUT = 9,
    OTHER_ALARM = 10
};

// 校准方式枚举
enum class CalibrationMethod : uint16_t {
    MANUAL_CALIBRATION = 0,
    AUTO_CALIBRATION = 1
};

// 零点校准结果/量程校准结果/标液核查结果枚举
enum class CalibrationResult : uint16_t {
    NONE = 0,
    VALID = 1,
    DEVIATION = 2
};

// 比色法光源枚举
enum class ColorimetricLightSource : uint16_t {
    SINGLE_SPECTRUM = 0,
    MULTI_SPECTRUM = 1
};

// 核查方式枚举
enum class CheckMethod : uint16_t {
    MANUAL_CHECK = 0,
    AUTO_CHECK = 1
};

// 主状态枚举
enum class MainStatus : uint16_t {
    IDLE = 1,
    AUTO_MEASUREMENT = 2,
    AUTO_CALIBRATION = 3,
    AUTO_STANDARD_CHECK = 4,
    MAINTENANCE = 5,
    FAULT = 6
};

// 子状态（运行状态）枚举
enum class SubStatusRunning : uint16_t {
    IDLE_SUB = 0,
    CLEAN_PREPROCESSING = 1,
    EXTRACT_SAMPLE = 2,
    CLEAN_REACTION_POOL = 3,
    FLOW_SAMPLING = 4,
    CONSTANT_TEMPERATURE_DIGESTION = 5,
    REACTION_POOL_COOLING = 6,
    REAGENT_A_INJECTION = 7,
    REAGENT_B_INJECTION = 8,
    REAGENT_C_INJECTION = 9,
    REAGENT_D_INJECTION = 10,
    EMPTY_REACTION_POOL = 11,
    WASTE_DISCHARGE_CLEANING = 12,
    CLEAN_WATER_PIPE = 13,
    CLEANING_SOLUTION_INJECTION = 14,
    CLEAN_WATER_SOAK_REACTION_POOL = 15,
    WATER_SAMPLE_INJECTION = 16,
    CARRIER_LIQUID_INJECTION = 17,
    ANALYZE_WATER_SAMPLE = 18
};

// 子状态（维护状态）枚举
enum class SubStatusMaintenance : uint16_t {
    MANUAL_MEASURE_SAMPLE = 1,
    MANUAL_ZERO_CALIBRATION = 2,
    MANUAL_RANGE_CALIBRATION = 3,
    MANUAL_STANDARD_CHECK = 4,
    ACTUAL_SAMPLE_COMPARISON = 5
};

// 子状态（自动校准状态）枚举
enum class SubStatusAutoCalibration : uint16_t {
    ZERO_CALIBRATION = 1,
    RANGE_CALIBRATION = 2,
    ANALYZE_CHECK_LIQUID = 3,
    INJECT_CHECK_LIQUID = 4
};

// 子状态（自动标液核查状态）枚举
enum class SubStatusAutoStandardCheck : uint16_t {
    NONE_AUTO_STANDARD_CHECK = 0
};

// 测试样品标记枚举
enum class TestSampleMark : uint16_t {
    NONE_TEST_SAMPLE = 0,
    AUTO_MEASURE_WATER_SAMPLE = 1,
    AUTO_MEASURE_ZERO_SAMPLE = 2,
    AUTO_MEASURE_RANGE_CALIBRATION_SAMPLE = 3,
    AUTO_MEASURE_STANDARD_CHECK_SAMPLE = 4,
    MANUAL_MEASURE_WATER_SAMPLE = 5,
    MANUAL_MEASURE_ZERO_SAMPLE = 6,
    MANUAL_MEASURE_RANGE_CALIBRATION_SAMPLE = 7,
    MANUAL_MEASURE_STANDARD_CHECK_SAMPLE = 8
};

// 测试结果标记枚举
enum class TestResultMark : uint16_t {
    NORMAL = 1,
    WATER_QUALITY_ANALYZER_FAULT = 2
};

// 数据标识枚举
enum class DataIdentifier : uint16_t {
    N = 0, // 无效测量值
    A = 1, // 有效测量值
    D = 2, // 设备上电启动或软件重启时间
    M = 3, // 维护数据
    C = 4, // 校准数据
    T = 5, // 取水时间
    TD = 6, // 消解数据
    K = 7  // 核查数据
};

// 抽象基类：ModbusRegister
class ModbusRegister {
public:
    ModbusRegister(uint16_t address, AccessType accessType, DataType dataType, const std::string& name)
        : address_(address), accessType_(accessType), dataType_(dataType), name_(name) {}
    virtual ~ModbusRegister() = default;

    uint16_t getAddress() const { return address_; }
    AccessType getAccessType() const { return accessType_; }
    DataType getDataType() const { return dataType_; }
    const std::string& getName() const { return name_; }

    // 纯虚函数，用于从Modbus数据中解析值
    virtual bool parseValue(const std::vector<uint16_t>& data) = 0;
    // 纯虚函数，用于将值转换为Modbus数据
    virtual std::vector<uint16_t> toModbusData() const = 0;

protected:
    uint16_t address_;
    AccessType accessType_;
    DataType dataType_;
    std::string name_;
};

// 模板类：ModbusRegisterT，用于具体数据类型的寄存器
template<typename T>
class ModbusRegisterT : public ModbusRegister {
public:
    ModbusRegisterT(uint16_t address, AccessType accessType, DataType dataType, const std::string& name)
        : ModbusRegister(address, accessType, dataType, name), value_() {}

    T getValue() const { return value_; }
    void setValue(T value) { value_ = value; }

protected:
    T value_;
};

// 16位无符号整数寄存器
class UInt16Register : public ModbusRegisterT<uint16_t> {
public:
    UInt16Register(uint16_t address, AccessType accessType, const std::string& name)
        : ModbusRegisterT(address, accessType, DataType::UINT16, name) {}

    bool parseValue(const std::vector<uint16_t>& data) override {
        if (data.size() * 2 < sizeof(uint16_t)) return false; // 检查数据长度
        // Modbus通常是大端，这里假设数据已经按大端传输
        value_ = data[0];
        return true;
    }

    std::vector<uint16_t> toModbusData() const override {
        return {value_};
    }
};

// 32位浮点数寄存器
class Float32Register : public ModbusRegisterT<float> {
public:
    Float32Register(uint16_t address, AccessType accessType, const std::string& name)
        : ModbusRegisterT(address, accessType, DataType::FLOAT32, name) {}

    bool parseValue(const std::vector<uint16_t>& data) override {
        if (data.size() * 2 < sizeof(float)) return false; // 检查数据长度
        // Modbus浮点数通常是两个16位寄存器，需要组合
        // 假设Modbus浮点数是IEEE 754单精度浮点数，且高位在前
        uint32_t temp_val = (static_cast<uint32_t>(data[0]) << 16) | data[1];
        value_ = *reinterpret_cast<float*>(&temp_val);
        return true;
    }

    std::vector<uint16_t> toModbusData() const override {
        uint32_t temp_val = *reinterpret_cast<const uint32_t*>(&value_);
        return {static_cast<uint16_t>((temp_val >> 16) & 0xFFFF), static_cast<uint16_t>(temp_val & 0xFFFF)};
    }
};

// Modbus协议管理器 (使用工厂模式和单例模式)
class ModbusProtocolManager {
public:
    static ModbusProtocolManager& getInstance() {
        static ModbusProtocolManager instance;
        return instance;
    }

    // 根据寄存器地址获取寄存器对象
    ModbusRegister* getRegister(uint16_t address) {
        auto it = registers_.find(address);
        if (it != registers_.end()) {
            return it->second;
        }
        return nullptr;
    }

    // 初始化所有寄存器
    void initializeRegisters() {
        // 读写类参数
        registers_[0] = new UInt16Register(0, AccessType::READ_ONLY, "是否有有效测量值");
        registers_[1] = new Float32Register(1, AccessType::READ_ONLY, "测量值");
        registers_[3] = new Float32Register(3, AccessType::READ_ONLY, "当前测量值对应的信号值或者吸光度");
        registers_[5] = new UInt16Register(5, AccessType::READ_ONLY, "取水时间，年");
        registers_[6] = new UInt16Register(6, AccessType::READ_ONLY, "取水时间，月");
        registers_[7] = new UInt16Register(7, AccessType::READ_ONLY, "取水时间，日");
        registers_[8] = new UInt16Register(8, AccessType::READ_ONLY, "取水时间，时");
        registers_[9] = new UInt16Register(9, AccessType::READ_ONLY, "取水时间，分");
        registers_[10] = new UInt16Register(10, AccessType::READ_ONLY, "取水时间，秒");
        registers_[11] = new UInt16Register(11, AccessType::READ_ONLY, "是否存在设备上电启动或软件重启时间");
        registers_[12] = new UInt16Register(12, AccessType::READ_ONLY, "重启时间，年");
        registers_[13] = new UInt16Register(13, AccessType::READ_ONLY, "重启时间，月");
        registers_[14] = new UInt16Register(14, AccessType::READ_ONLY, "重启时间，日");
        registers_[15] = new UInt16Register(15, AccessType::READ_ONLY, "重启时间，时");
        registers_[16] = new UInt16Register(16, AccessType::READ_ONLY, "重启时间，分");
        registers_[17] = new UInt16Register(17, AccessType::READ_ONLY, "重启时间，秒");
        registers_[18] = new UInt16Register(18, AccessType::READ_ONLY, "仪器状态");
        registers_[19] = new UInt16Register(19, AccessType::READ_ONLY, "报警类型");
        registers_[20] = new UInt16Register(20, AccessType::READ_ONLY, "有无零点校准结果");
        registers_[21] = new Float32Register(21, AccessType::READ_ONLY, "零点校准浓度测量值");
        registers_[23] = new Float32Register(23, AccessType::READ_ONLY, "零点校准信号值");
        registers_[25] = new UInt16Register(25, AccessType::READ_ONLY, "零点校准结果");
        registers_[26] = new UInt16Register(26, AccessType::READ_ONLY, "零点校准时间，年");
        registers_[27] = new UInt16Register(27, AccessType::READ_ONLY, "零点校准时间，月");
        registers_[28] = new UInt16Register(28, AccessType::READ_ONLY, "零点校准时间，日");
        registers_[29] = new UInt16Register(29, AccessType::READ_ONLY, "零点校准时间，时");
        registers_[30] = new UInt16Register(30, AccessType::READ_ONLY, "零点校准时间，分");
        registers_[31] = new UInt16Register(31, AccessType::READ_ONLY, "零点校准时间，秒");
        registers_[32] = new UInt16Register(32, AccessType::READ_ONLY, "有无校满校准结果");
        registers_[33] = new Float32Register(33, AccessType::READ_ONLY, "量程校准浓度测量值");
        registers_[35] = new Float32Register(35, AccessType::READ_ONLY, "量程校准对应信号值");
        registers_[37] = new UInt16Register(37, AccessType::READ_ONLY, "量程校准结果");
        registers_[38] = new UInt16Register(38, AccessType::READ_ONLY, "量程校准时间，年");
        registers_[39] = new UInt16Register(39, AccessType::READ_ONLY, "量程校准时间，月");
        registers_[40] = new UInt16Register(40, AccessType::READ_ONLY, "量程校准时间，日");
        registers_[41] = new UInt16Register(41, AccessType::READ_ONLY, "量程校准时间，时");
        registers_[42] = new UInt16Register(42, AccessType::READ_ONLY, "量程校准时间，分");
        registers_[43] = new UInt16Register(43, AccessType::READ_ONLY, "量程校准时间，秒");
        registers_[44] = new UInt16Register(44, AccessType::READ_ONLY, "校准方式");
        registers_[45] = new UInt16Register(45, AccessType::READ_ONLY, "自动校准间隔");
        registers_[46] = new Float32Register(46, AccessType::READ_ONLY, "斜率");
        registers_[48] = new Float32Register(48, AccessType::READ_ONLY, "截距");
        registers_[50] = new Float32Register(50, AccessType::READ_ONLY, "修正因子");
        registers_[52] = new Float32Register(52, AccessType::READ_ONLY, "修正偏差");
        registers_[54] = new Float32Register(54, AccessType::READ_ONLY, "是否有消解动作");
        registers_[56] = new UInt16Register(56, AccessType::READ_ONLY, "消解时长");
        registers_[57] = new Float32Register(57, AccessType::READ_ONLY, "消解温度");
        registers_[61] = new Float32Register(61, AccessType::READ_ONLY, "当前量程 mg/L");
        registers_[63] = new Float32Register(63, AccessType::READ_ONLY, "测量精度 95%");
        registers_[65] = new Float32Register(65, AccessType::READ_ONLY, "零点校准浓度");
        registers_[67] = new Float32Register(67, AccessType::READ_ONLY, "零点校准信号值或者吸光度");
        registers_[69] = new Float32Register(69, AccessType::READ_ONLY, "量程校准浓度");
        registers_[71] = new Float32Register(71, AccessType::READ_ONLY, "量程校准信号值或者吸光度");
        registers_[73] = new Float32Register(73, AccessType::READ_ONLY, "核查标样浓度");
        registers_[75] = new Float32Register(75, AccessType::READ_ONLY, "核查测量值");
        registers_[77] = new Float32Register(77, AccessType::READ_ONLY, "核查信号值或者吸光度");
        registers_[79] = new UInt16Register(79, AccessType::READ_ONLY, "标样核查时间，年");
        registers_[80] = new UInt16Register(80, AccessType::READ_ONLY, "标样核查时间，月");
        registers_[81] = new UInt16Register(81, AccessType::READ_ONLY, "标样核查时间，日");
        registers_[82] = new UInt16Register(82, AccessType::READ_ONLY, "标样核查时间，时");
        registers_[83] = new UInt16Register(83, AccessType::READ_ONLY, "标样核查时间，分");
        registers_[84] = new UInt16Register(84, AccessType::READ_ONLY, "标样核查时间，秒");
        registers_[85] = new UInt16Register(85, AccessType::READ_ONLY, "是否出错标志");
        registers_[86] = new UInt16Register(86, AccessType::READ_ONLY, "测试间隔");
        registers_[105] = new UInt16Register(105, AccessType::READ_ONLY, "反控启动测量结果");
        registers_[106] = new UInt16Register(106, AccessType::READ_ONLY, "反控校时结果");
        registers_[107] = new UInt16Register(107, AccessType::READ_ONLY, "反控校准结果");
        registers_[108] = new UInt16Register(108, AccessType::READ_ONLY, "反控核查结果");
        registers_[109] = new UInt16Register(109, AccessType::READ_ONLY, "反控停止结果");
        registers_[110] = new UInt16Register(110, AccessType::READ_ONLY, "反控手动分析结果");
        registers_[111] = new UInt16Register(111, AccessType::READ_ONLY, "降温时间");
        registers_[112] = new Float32Register(112, AccessType::READ_ONLY, "仪器量程上限");
        registers_[179] = new UInt16Register(179, AccessType::READ_ONLY, "远程分析返回结果");
        registers_[180] = new UInt16Register(180, AccessType::READ_ONLY, "写入时间返回结果");
        registers_[181] = new UInt16Register(181, AccessType::READ_ONLY, "校正标一返回结果");
        registers_[182] = new UInt16Register(182, AccessType::READ_ONLY, "校正标二返回结果");
        registers_[183] = new UInt16Register(183, AccessType::READ_ONLY, "执行清洗返回结果");

        registers_[197] = new UInt16Register(197, AccessType::READ_WRITE, "校正标一");
        registers_[198] = new UInt16Register(198, AccessType::READ_WRITE, "校正标二");
        registers_[199] = new UInt16Register(199, AccessType::READ_WRITE, "启动测量指令");
        registers_[200] = new UInt16Register(200, AccessType::READ_WRITE, "校时指令标识");
        registers_[201] = new UInt16Register(201, AccessType::READ_WRITE, "校时指令年");
        registers_[202] = new UInt16Register(202, AccessType::READ_WRITE, "校时指令月");
        registers_[203] = new UInt16Register(203, AccessType::READ_WRITE, "校时指令日");
        registers_[204] = new UInt16Register(204, AccessType::READ_WRITE, "校时指令时");
        registers_[205] = new UInt16Register(205, AccessType::READ_WRITE, "校时指令分");
        registers_[206] = new UInt16Register(206, AccessType::READ_WRITE, "校时指令秒");
        registers_[207] = new UInt16Register(207, AccessType::READ_WRITE, "启动清洗指令");
        registers_[208] = new UInt16Register(208, AccessType::READ_WRITE, "启动核查指令");
        registers_[209] = new UInt16Register(209, AccessType::READ_WRITE, "启动停止指令");
        registers_[210] = new UInt16Register(210, AccessType::READ_WRITE, "远程手动测量");
        registers_[211] = new Float32Register(211, AccessType::READ_ONLY, "标二吸光度");
        registers_[213] = new Float32Register(213, AccessType::READ_ONLY, "校准后空白吸光度");
        registers_[215] = new Float32Register(215, AccessType::READ_ONLY, "校准前校准过程值");
        registers_[217] = new Float32Register(217, AccessType::READ_ONLY, "校准前空白吸光度");
        registers_[219] = new Float32Register(219, AccessType::READ_ONLY, "校准前曲线斜率");
        registers_[221] = new Float32Register(221, AccessType::READ_ONLY, "校准前曲线截距");
        registers_[223] = new Float32Register(223, AccessType::READ_ONLY, "校准线性变动");
        registers_[225] = new Float32Register(225, AccessType::READ_ONLY, "校正标一变化");
        registers_[227] = new Float32Register(227, AccessType::READ_ONLY, "校正标二变化");
        registers_[229] = new Float32Register(229, AccessType::READ_ONLY, "标样核查偏差百分比");
        registers_[231] = new Float32Register(231, AccessType::READ_ONLY, "标样核查设置浓度");
        registers_[233] = new UInt16Register(233, AccessType::READ_ONLY, "量程下限");
        registers_[235] = new UInt16Register(235, AccessType::READ_ONLY, "跨度校准标识");
        registers_[236] = new UInt16Register(236, AccessType::READ_ONLY, "标液核查结果");
        registers_[237] = new UInt16Register(237, AccessType::READ_ONLY, "比色法光源");
        registers_[238] = new UInt16Register(238, AccessType::READ_ONLY, "核查方式");
        registers_[239] = new UInt16Register(239, AccessType::READ_ONLY, "自动核查间隔");
        registers_[352] = new Float32Register(352, AccessType::READ_ONLY, "测量浓度(带维护数据)");
        registers_[354] = new UInt16Register(354, AccessType::READ_ONLY, "数据标识");

        // 新增参数
        registers_[1000] = new Float32Register(1000, AccessType::READ_ONLY, "检出限");
        registers_[1002] = new Float32Register(1002, AccessType::READ_ONLY, "零点校准浓度允许偏差值");
        registers_[1004] = new Float32Register(1004, AccessType::READ_ONLY, "零点校准浓度测量值");
        registers_[1006] = new Float32Register(1006, AccessType::READ_ONLY, "零点校准测量偏差");
        registers_[1008] = new Float32Register(1008, AccessType::READ_ONLY, "量程校准浓度允许偏差值");
        registers_[1010] = new Float32Register(1010, AccessType::READ_ONLY, "量程校准浓度测量值");
        registers_[1012] = new Float32Register(1012, AccessType::READ_ONLY, "量程校准测量偏差");
        registers_[1014] = new Float32Register(1014, AccessType::READ_ONLY, "标液核查浓度允许偏差值");
        registers_[1020] = new UInt16Register(1020, AccessType::READ_ONLY, "主状态");
        registers_[1021] = new UInt16Register(1021, AccessType::READ_ONLY, "子状态（运行状态）");
        registers_[1022] = new UInt16Register(1022, AccessType::READ_ONLY, "测试样品标记");
        registers_[1023] = new UInt16Register(1023, AccessType::READ_ONLY, "测试结果标记");
    }

    // 清理资源
    ~ModbusProtocolManager() {
        for (auto const& [key, val] : registers_) {
            delete val;
        }
        registers_.clear();
    }

private:
    ModbusProtocolManager() = default; // 私有构造函数
    ModbusProtocolManager(const ModbusProtocolManager&) = delete; // 禁用拷贝构造
    ModbusProtocolManager& operator=(const ModbusProtocolManager&) = delete; // 禁用赋值操作符

    std::map<uint16_t, ModbusRegister*> registers_;
};

#endif // MODBUS_PROTOCOL_H


